/*
	Config class holds global parameters for execution, as read from config file
*/
#ifndef CONFIG_H_
#define CONFIG_H_
#include <string>
#include <stdlib.h>
#include <iostream>
#include <fstream>
#include <map>

using namespace std;

#define MAX_INT 4000000000

typedef struct _CpuParams{
		bool forceAssignment; // a flag indicating whether thread affinity to CPUs should be enforced
		bool crossChipWorkStealing; // a flag indicating whether wrok stealing between chips (work groups) is allowed
		int* prods;  // if forced affinity - which cores are producers cores
		int prodCoreNum;  // if forced affinity - how many cores are producer cores
		int* cons;  // if forced affinity - which cores are consumers cores
		int consCoreNum;  // if forced affinity - how many cores are consumer cores
		int** chips; // division of cores (threads) into working groups (chips)
		int chipNum;  // number of chips
		int coresPerChip;  // number of cores per chip
		int prodThreadsNum; // number of producer threads
		int consThreadsNum; // number of consumer threads
}CpuParams;

class Config{

		// split str into substrings seperated by <seperator>, and return an array of these substrings
		static string* stringSplit(const string str, const char seperator, int& arrLen);

		// parse a list of core numbers from configuration file
		static int* parseThreadCores(string coresString, int& coreNum);

		// parse division of cores into chips
		static int** parseChipCores(string chips, int& chipNum, int& coresPerChip);

		// initialize and set {consumer,producer}To{Chip,Core} mappings
		static void initThreadsToChipMap();
public:
		//static const int numOfCpus = 32;  // machine dependent
		
		static CpuParams* cpus;

		static map<int,int>* consumerToChip; // mapping of consumers to chips (work groups)
		static map<int,int>* consumerToCore; // mapping of consumers to cores
		static map<int,int>* producerToChip; // mapping of producers to chips
		static map<int,int>* producerToCore; // mapping of producers to cores
		
		static int* producerIds;  	// array of producer thread ids (assigned in the program. not pthread_t identifiers)
		static int* consumerIds;	// array of consumer thread ids (assigned in the program. not pthread_t identifiers)
		
		/* producers input intervals */
		static int timeBetweenPeaks;
		static int peakLength;

		/* test runtime */
		static unsigned long timeToRun;

		/* container parameters */
		static string containerType;  // type of main container
		static string perChipContainerType;  // For complex containers (ChipAwareContainer): type of base container
		static int perChipContainersNum;  // number of containers per chip

		/******** fields currently not in use *************************************/
		/*
		//static int consFailuresThreshold;  // for bursty producers experiment (not in use) - when to start counting idle time for consumers (number of null tasks retrieved)
		
		//flags to indicate which statistics will be gathered and displayed - by default switching off the statistics
		static bool contentionStatistics;  //statistics about CAS operations
		static bool exitsStatistics;  // statistics about exits from chips

		//for busy noise tests
		static int shortTaskLength;
		static int longTaskRange;

		// types of producers/consumers used (default - "regular")
		static string consType;
		static string prodType;

		//Quasi-linearizable queues parameters - what are these for?
		static string quasiType;
		static int quasiFactor;
		static int qRandomTries;
		*/
		/************************************************************************/
		
		// read configuration file and set Config's fields accordingly
		static void readConfiguration(const char* configFile);
		
		static int getChipByCoreId(int coreId);

		static void init(int* producerIds, int* consumerIds);

		static void freeMem();

};
#endif /* CONFIG_H_ */
